#include "core.h"
#include "ICore.h"
#include <errno.h>

// ....................................................................................................................
// Exportovana funkcia: Nastavenie casu a datumu suboru
// Vstup:
//			pName - nazov
//			pDCreate - datum vytvorenia alebo 0 pre nenastavenie
//			pDModify - datum zmeny alebo 0 pre nenastavenie
//			pDLastAccess - datum posledneho pristupu alebo 0 pre nenastavenie
// Vystup:
//			0 - OK, < 0 chyba
// ....................................................................................................................
INT32 __stdcall SetFileDateTime(PCHAR pName, UINT64 pDCreate, UINT64 pDModify, UINT64 pDLastAccess) {
	FILETIME F1, F2, F3;
	ULARGE_INTEGER U;

	U.QuadPart = pDCreate; F1.dwHighDateTime = U.HighPart; F1.dwLowDateTime = U.LowPart;
	U.QuadPart = pDModify; F2.dwHighDateTime = U.HighPart; F2.dwLowDateTime = U.LowPart;
	U.QuadPart = pDLastAccess; F3.dwHighDateTime = U.HighPart; F3.dwLowDateTime = U.LowPart;

	if ((pDCreate == 0) && (pDModify == 0) && (pDLastAccess == 0)) return 0; // Ziadna ziadana zmena?

	HANDLE F = ::CreateFile(pName, GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); // Otvorim subor
	if (F == INVALID_HANDLE_VALUE) return ::GetLastError(); // Vratim chybu

	int R = 0;
	if (::SetFileTime(F, pDCreate == 0 ? NULL : &F1, pDLastAccess == 0 ? NULL : &F3, pDModify == 0 ? NULL : &F2) == 0) { // Volam nastavenie stavu
		R = ::GetLastError(); // Ziskam kod chyby
	}

	::CloseHandle(F); // Zrusim handle

	return R; // Vsetko OK
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Citanie zo suboru
// Vstup:
//			pHandle - handle suboru
//			pLength - dlzka
//			pData - data
// Vystup:
//			0 - OK, < 0 chyba
// ....................................................................................................................
INT32 __stdcall WriteToLocalFile(FILE *pHandle, void* pData, INT32 pLength) {
	if (fwrite(pData, 1, pLength, pHandle) == pLength) return 0; // Zapisem
	if (errno == ENOSPC) return -16; // Plny disk?
	return -1; // Chyba
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Citanie zo suboru
// Vstup:
//			pHandle - handle suboru
//			pMaxLength - max. dlzka
// Vystup:
//			pData - nacitane data
//			0 - koniec, > 1 pocet nacitanych dat, < 0 chyba
// ....................................................................................................................
INT32 __stdcall ReadFromLocalFile(FILE *pHandle, void* pData, INT32 pMaxLength) {
	return (pHandle == NULL) ? -1 : (INT32)fread(pData, 1, pMaxLength, pHandle);
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Vytvorenie suboru na zapis
// Vstup:
//			pHandle - handle suboru
// Vystup:
//			ziaden
// ....................................................................................................................
FILE* __stdcall CreateLocalFile(PCHAR pFileName) {
	return fopen(pFileName, "wb+");
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Otvorenie suboru na citanie
// Vstup:
//			pHandle - handle suboru
// Vystup:
//			ziaden
// ....................................................................................................................
void __stdcall CloseLocalFile(FILE *pHandle) {
	if (pHandle != NULL) fclose(pHandle);
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Otvorenie suboru na citanie
// Vstup:
//			pFileName - nazov suboru
// Vystup:
//			handle
// ....................................................................................................................
FILE* __stdcall OpenLocalFileForRead(PCHAR pFileName) {
	return fopen(pFileName, "rb"); // Volam otvorenie
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Uvolnenie alokovanej pamate
// Vstup:
//			pCapacity - kapacita pamate
// Vystup:
//			handle
// ....................................................................................................................
void* __stdcall AllocateMemory(INT32 pCapacity) {
	return new BYTE[pCapacity]; // Alokujem
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Uvolnenie alokovanej pamate
// Vstup:
//			pHandle - handle na pamatove miesto
// Vystup:
//			ziaden
// ....................................................................................................................
void __stdcall FreeMemory(void *pHandle) {
	if (pHandle != NULL) delete (PBYTE)pHandle; // Zrusim pamat
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Ziskanie kapacity zariadenia
// Vstup:
//			pPath - cesta na zariadenie
// Vystup:
//			kapacita alebo -1 pre chybu
// ....................................................................................................................
INT64 __stdcall GetDeviceCapacity(PCHAR pPath) {
	ULARGE_INTEGER U;
	return ::GetDiskFreeSpaceEx(pPath, NULL, &U, NULL) != 0 ? (INT64)U.QuadPart : -1;
}
// ....................................................................................................................
// ....................................................................................................................
// Exportovana funkcia: Ziskanie volneho miesta na zariadeni
// Vstup:
//			pPath - cesta na zariadenie
// Vystup:
//			kapacita alebo -1 pre chybu
// ....................................................................................................................
INT64 __stdcall GetDeviceFreeSpace(PCHAR pPath) {
	ULARGE_INTEGER U;
	return ::GetDiskFreeSpaceEx(pPath, &U, NULL, NULL) != 0 ? (INT64)U.QuadPart : -1;
}
// ....................................................................................................................
// ....................................................................................................................
// Test platneho indexu
// Vstup:
//			pIndex - testovany index
//			pMin - minimum
//			pMax - maximum
// Vystup:
//			true / false
// ....................................................................................................................
bool __fastcall ICore::IsValidIndex(INT32 pIndex, INT32 pMin, INT32 pMax) {
	return (pIndex >= pMin) && (pIndex < pMax);
}
// ....................................................................................................................
// ....................................................................................................................
// Extrahovanie cesty
// Vstup:
//			pValue - plna cesta
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall ICore::ExtractPath(IString *pValue, IString *Result) {
	if (pValue->Length < 4) Result->Truncate();
	else {
		int I = pValue->ReverseFindChar('\\'); // Hladam oddelovac
		*Result = *pValue;
		Result->Truncate(I == 2 ? 3 : I); // Skratim
	}
}
// ....................................................................................................................
// ....................................................................................................................
// Extrahovanie nazvu
// Vstup:
//			pValue - plna cesta
// Vystup:
//			Result - vysledok
// ....................................................................................................................
void __fastcall ICore::ExtractName(IString *pValue, IString *Result) {
	if (pValue->Length < 4) *Result = *pValue;
	else {
		IString S(pValue); S.DeleteLastChar('\\'); // Vymazem posledny oddelovac
		int I = S.ReverseFindChar('\\');  // Hladam oddelovac
		if (I == -1) Result->Truncate(); // Nic?
		else S.RightSubstring(I + 1, Result); // Extrahujem meno
	}
}
// ....................................................................................................................

